package com.thread.chapter3;

import cn.hutool.core.thread.ThreadUtil;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
public class Demo3_1_11_3 {

    private List<String> list = new ArrayList<>();

    synchronized public void push() {
        try {
            while (list.size() == 1) {
                System.out.println("生产者拿到锁,wait并释放锁:" + Thread.currentThread().getName());
                this.wait();
            }
            list.add("元素:" + Math.random());
            System.out.println(Thread.currentThread().getName() + "生产者拿到锁,生产push=" + list.size());
            this.notifyAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    synchronized public String pop() {
        String returnValue = "";
        try {
            while (list.size() == 0) {
                System.out.println("消费者拿到锁,wait并释放锁:" + Thread.currentThread().getName());
                this.wait();
            }
            returnValue = list.get(0);
            list.remove(0);
            System.out.println(Thread.currentThread().getName() + "消费者拿到锁,消费pop=" + list.size());
            this.notify();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnValue;
    }

    static class P {
        private Demo3_1_11_3 lock;

        public P(Demo3_1_11_3 lock) {
            this.lock = lock;
        }

        public void pushService() {
            lock.push();
        }
    }

    static class C {
        private Demo3_1_11_3 lock;

        public C(Demo3_1_11_3 lock) {
            this.lock = lock;
        }

        public void popService() {
            lock.pop();
        }
    }

    public static void main(String[] args) {
        //多生产者多个消费者,List最大容量是1
        Demo3_1_11_3 lock = new Demo3_1_11_3();
        new Thread(() -> {
            while (true) {
                new P(lock).pushService();
            }
        }).start();
        new Thread(() -> {
            while (true) {
                new P(lock).pushService();
            }
        }).start();
        new Thread(() -> {
            while (true) {
                new P(lock).pushService();
            }
        }).start();
        new Thread(() -> {
            while (true) {
                new P(lock).pushService();
            }
        }).start();

        ThreadUtil.sleep(5000);
        new Thread(() -> {
            while (true) {
                new C(lock).popService();
            }
        }).start();
        new Thread(() -> {
            while (true) {
                new C(lock).popService();
            }
        }).start();
        new Thread(() -> {
            while (true) {
                new C(lock).popService();
            }
        }).start();

    }
}
